package com.zkyt.lib_msdk_ext.component

import com.geoai.mavlink.geoainet.base.mavlinkcore.engine.GEOAIError
import com.geoai.mavlink.geoainet.base.mavlinkcore.interfaces.CompletionCallback
import com.geoai.mavlink.geoainet.flycontroller.info.FlyControllerStateInfo
import com.geoai.mavlink.geoainet.flycontroller.info.ParachuteStateInfo
import com.geoai.mavlink.geoainet.mission.MissionManager
import com.geoai.mavlink.geoainet.mission.enums.MissionReloadMode
import com.geoai.mavlink.geoainet.mission.enums.MissionSignalLostMode
import com.geoai.mavlink.geoainet.mission.enums.MissionState
import com.geoai.mavlink.geoainet.mission.enums.OrbitYawBehaviour
import com.geoai.mavlink.geoainet.mission.factory.MissionItemBuilder
import com.geoai.mavlink.geoainet.mission.info.MissionStateInfo
import com.geoai.mavlink.geoainet.mission.interfaces.IBaseMissionManager
import com.geoai.mavlink.geoainet.mission.interfaces.IMissionStateListener
import com.zkyt.lib_msdk_ext.common.SDKExceptionWrapper
import com.zkyt.lib_msdk_ext.common.SDKExtUtil
import io.reactivex.Completable
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.subjects.BehaviorSubject
import java.util.Optional

/**
 * Created by chenyu on 2024/1/10
 * Description:
 */
object MissionManagerExt: ISDKExt<IBaseMissionManager>, IRemovableComp {
    private var originMissionStateObservable =
        BehaviorSubject.createDefault<Optional<MissionStateInfo>>(Optional.ofNullable(null))
    private val isConnectSubject = BehaviorSubject.createDefault(false)
    private var missionManager: IBaseMissionManager? = null

    override fun init(originManager: IBaseMissionManager) {
        missionManager = originManager
        isConnectSubject.onNext(true)
        missionManager?.setMissionStateListener(object : IMissionStateListener{
            override fun onMissionState(p0: MissionState, totalWaypoint: Int, currentWaypoint: Int, currentAction: Int) {
                val missionInfo = (missionManager as MissionManager).missionInfo
                originMissionStateObservable.onNext(Optional.of(missionInfo))
            }

            override fun onMissionStart() {
            }

            override fun onMissionFinish() {
            }
        })
    }

    override fun isConnected(): Boolean {
        return isConnectSubject.value!!
    }

    override fun getConnectedObservable(): Observable<Boolean> {
        return isConnectSubject.hide()
    }

    override fun destroy() {
        isConnectSubject.onNext(false)
        originMissionStateObservable.onNext(Optional.ofNullable(null))
        missionManager = null
    }

    override fun getOriginManager(): IBaseMissionManager? {
        return missionManager
    }

    fun getMissionStateObservable(): Observable<Optional<MissionStateInfo>> {
        return originMissionStateObservable.hide()
    }

    fun startMissionRx(): Completable {
        return Completable.create { emitter ->
            missionManager?.startMission {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun pauseMissionRx(): Completable {
        return Completable.create { emitter ->
            missionManager?.pauseMission {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun continueMissionRx(): Completable {
        return Completable.create { emitter ->
            missionManager?.continueMission {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun stopMissionRx(): Completable {
        return Completable.create { emitter ->
            missionManager?.stopMission {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun stopMissionUploadRx(): Completable {
        return Completable.create { emitter ->
            missionManager?.stopMissionUpload {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun sendOrbitCommandRx(
        latitude: Double,
        longitude: Double,
        altitude: Float,
        radius: Float,
        speed: Float,
        yawBehaviour: OrbitYawBehaviour
    ): Completable {
        return Completable.create { emitter ->
            missionManager?.sendOrbitCommand(latitude, longitude, altitude, radius, speed, yawBehaviour) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun downloadMissionRx(mode: MissionReloadMode): Single<MissionItemBuilder> {
        return Single.create { emitter ->
            missionManager?.downloadMission(mode, object : CompletionCallback.ICompletionCallbackWith<MissionItemBuilder.Builder>{
                override fun onFailure(geoaiError: GEOAIError) {
                    emitter.onError(SDKExceptionWrapper(geoaiError))
                }

                override fun onResult(t: MissionItemBuilder.Builder) {
                    emitter.onSuccess(t.build())
                }
            })
        }
    }

    fun createBreakPointInfoRx(): Single<MissionItemBuilder> {
        return Single.create { emitter ->
            missionManager?.createBreakPointInfo(object : CompletionCallback.ICompletionCallbackWith<MissionItemBuilder.Builder>{
                override fun onFailure(geoaiError: GEOAIError) {
                    emitter.onError(SDKExceptionWrapper(geoaiError))
                }

                override fun onResult(t: MissionItemBuilder.Builder) {
                    emitter.onSuccess(t.build())
                }
            })
        }
    }

    fun setMissionLostBehaviorRx(missionLostBehavior: MissionSignalLostMode): Completable {
        return Completable.create { emitter ->
            missionManager?.setMissionSignalLostBehavior(missionLostBehavior) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getMissionLostBehaviorRx(): Single<MissionSignalLostMode> {
        return Single.create { emitter ->
            missionManager?.getMissionSignalLostBehavior(object : CompletionCallback.ICompletionCallbackWith<MissionSignalLostMode>{
                override fun onFailure(geoaiError: GEOAIError) {
                    emitter.onError(SDKExceptionWrapper(geoaiError))
                }

                override fun onResult(t: MissionSignalLostMode) {
                    emitter.onSuccess(t)
                }
            })
        }
    }
}